Tutoriel : Reverse-Proxy avec Docker

touatily

1 – Introduction

Dans ce tutoriel, on va voir comment mettre en place, étape par étape, un reverse-proxy dans un container docker. On va créer un container reverse-proxy et trois containers serveurs web qui, chacun, se trouve dans son propre réseau.

Le reverse-proxy va nous permettre de déployer plusieurs applications web (sites web) sur la même machine qui seront accessibles avec la même adresse IP. L’aiguillage des requêtes se fait selon le nom de domaine de chaque site par le reverse-proxy.

2 – Architecture générale

Le système qu’on veut mettre en place se compose d’un container reverse-proxy qui va recevoir toutes les requêtes HTTP, puis, en fonction du nom de domaine (dans l’url) le reverse-proxy aiguille ces requêtes vers les différents containers serveurs web.

Les containers serveur web peuvent être tous dans le même réseau comme ils peuvent aussi être dans des sous réseaux différents. Pour rester générique, on va considérer trois containers serveurs web se trouvant dans trois réseaux différents.

Pour que le containers reverse proxy puisse communiquer avec les containers serveurs web, il doit avoir une interface dans le même réseau que chacun d’eux en plus de son propore réseau.

Le tableau suivant résume les informations sur les différents containers :

Nom Container

Adresse IP

Réseau

Image Docker

URL

Serveur_web_1

192.168.0.3

192.168.0.0/24

web-server (httpd)

http://site1.com

Serveur_web_2

192.168.1.3

192.168.1.0/24

web-server (httpd)

http://site2.com

Serveur_web_3

192.168.2.3

192.168.2.0/24

web-server (httpd)

http://site3.com

Reverse-Proxy

192.168.0.2
192.168.1.2
192.168.2.2
172.17.0.2

192.168.0.0/24
192.168.1.0/24
192.168.2.0/24
172.17.0.0/16

reverse-proxy (nginx)

La figure suivante illustre l’architecture générale de notre système :

3 – Préparation des images docker

Pour mettre en place notre architecture décrite précédemment, on a besoin de préparer les images docker afin de créer les containers. Plus précisément, on a besoin de deux images docker :

3.1 – Solution 1 : avec des dockerfiles

Poour créer les images du reverse-proxy nginx et les serveurs web httpd en utilisant des dockerfiles, il faut copier ces deux textes suivants et les mettre dans deux fichiers, puis utiliser la commande « docker build » pour créer les deux images.

Le ficher « Dockerfile1 » pour le reverse-proxy nginx :

FROM nginx

RUN apt-get update

RUN apt-get install -y nano

RUN mkdir -p /etc/nginx/sites-enabled

RUN mkdir -p /etc/nginx/sites-available

ENTRYPOINT service nginx restart && /bin/bash

Le fichier « Dockerfile2 » pour le serveur web httpd :

FROM httpd

RUN apt-get update

RUN apt-get install -y nano

Maintenant que les deux fichiers dockerfile sont créés, il est possible de créer les deux images en faisant :

$ docker build -t touatily/reverse-proxy -f Dockerfile1 .

$ docker build -t touatily/web-server -f Dockerfile2 .

Les deux images s’appellent « touatily/reverse-proxy » et « touatily/web-server » respectivement. On peut vérifier ce en faisant :

$ docker images

3.2 – Solution 2 : téléchargement depuis dockerhub

La deuxième solution consiste à récupérer les images docker directement depuis docker hub. Pour cela, il faut taper les commandes suivantes :

$ docker pull touatily/reverse-proxy

$ docker pull touatily/web-server

Pour vérifier que les images ont bien été téléchargées depuis docker hub, il faut afficher la liste des images avec la commande « docker images » :

$ docker images

4 – Création des containers

À ce niveau, les images docker sont prêtes. Mais avant de créer les containers concrètement, il faut passer par plusieurs étapes :

4.1 – Préparation des réseaux

Comme indiqué précédemment, il nous faut un réseau par serveur web. Donc, en tout, on a besoin de trois réseaux en plus des réseaux créés par défaut par docker. Les informations sur les réseaux sont données plus haut dans le tableau récapitulatif.

Les commandes à exécuter sont les suivantes :

$ docker network create --subnet=192.168.0.0/24 --gateway=192.168.0.1 --driver=bridge réseau1

$ docker network create --subnet=192.168.1.0/24 --gateway=192.168.1.1 --driver=bridge réseau2

$ docker network create --subnet=192.168.2.0/24 --gateway=192.168.2.1 --driver=bridge réseau3

Pour vérifier que tout est en ordre, on peut afficher la liste des réseaux existants, et si tout s’est bien déroulé, on verra les trois réseaux (réseau1, réseau2, et réseau3) s’afficher en plus des trois réseaux créés par défaut :

docker network ls

4.2 – Lancement des containers

4.2.1 – Préparation des sites web

Avant de lancer les trois containers serveurs web, on crée trois répertoires (contenant chacun un fichier « index.html ») qui correspondent au trois sites web :

$ mkdir -p /root/websites/site1

$ echo "<h1>Site web 1</h1>" > /root/websites/site1/index.html

$ mkdir -p /root/websites/site2

$ echo "<h1>Site web 2</h1>" > /root/websites/site2/index.html

$ mkdir -p /root/websites/site3

$ echo "<h1>Site web 3</h1>" > /root/websites/site3/index.html

Evidemment, on peut mettre d’autres fichier HTML dans les trois répertoires, mais par soucis de simplicité, on se limite à des sites web constitués d’une seule page HTML.

4.2.2 – Création des containers serveurs web

Pour lancer les trois containers serveurs web il faut taper les commandes suivantes :

$ docker container run -itd --name serveur_web_1 --net réseau1 --ip 192.168.0.3 -v /root/websites/site1/:/usr/local/apache2/htdocs/  touatily/web-server

$ docker container run -itd --name serveur_web_2 --net réseau2 --ip 192.168.1.3 -v /root/websites/site2/:/usr/local/apache2/htdocs/ touatily/web-server

$ docker container run -itd --name serveur_web_3 --net réseau3 --ip 192.168.2.3 -v /root/websites/site3/:/usr/local/apache2/htdocs/ touatily/web-server

Maintenant, il nous reste à créer le container pour le reverse-proxy nginx.

$ sudo docker container run -itd --name reverse-proxy -p80:80 -v /srv/virtual-hosts/:/etc/nginx/sites-available/ touatily/reverse-proxy

Quelques remarques s’imposent :

4.3 – Configurations

4.3.1 – Côté reverse-proxy :

Il faudra créer les hôtes virtuels (un hôte virtuel par site web). Pour cela, dans le répertoire « /srv/virtual-hosts/ » qu’on a mappé sur le répertoire « /etc/nginx/sites-available/ » du container, on va créer un fichier de configuration par hôte virtuel (virtual host). Voici à quoi ressemble le fichier « site1.com » de configuration de l’hôte virtuel « site1.com » :

server {

        listen        80;

        server_name   site1.com;

        location / {

                proxy_pass  http://192.168.0.3;

        }

}

Il faudra créer deux autres fichiers qui correspondent aux deux autres hôtes virtuels « site2.com » et « site3.com » en changeant le texte surligné en jaune par les valeurs « site2.com » et « http://192.168.1.3 » pour l’hôte virtuel « site2.com » et par les valeurs « site3.com » et « http://192.168.2.3 » pour l’hôte virtuel « site3.com ».

Maintenant, il faut s’assurer que le reverse-proxy nginx prenne en considération ces hôtes virtuels en vérifiant son fichier de configuration « /etc/nginx/nginx.conf ». Plus exactement, il faut vérifier que la ligne « include /etc/nginx/sites-enabled/*; » est présente dans la partie « http { … } » :

...

http {

    ...

    include /etc/nginx/sites-enabled/*;

    ...

}

Pour ce, vous pouvez vous attachez au container puis modifier le fichier en faisant :

$ docker container attach reverse-proxy

root@f4be511eeda8:~# nano /etc/nginx/nginx.conf

Il nous reste encore à activer les différent hôtes virtuels et recharger la configuration pour que nginx prenne en considération des changement éffectués :

$ docker exec reverse-proxy ln -s /etc/nginx/sites-available/site1.com /etc/nginx/sites-enabled/site1.com

$ docker exec reverse-proxy ln -s /etc/nginx/sites-available/site2.com /etc/nginx/sites-enabled/site2.com

$ docker exec reverse-proxy ln -s /etc/nginx/sites-available/site3.com /etc/nginx/sites-enabled/site3.com

$ docker exec reverse service nginx reload

Reamrques :

Il faudra maintenant ajouter notre container reverse proxy aux différents réseaux déjà créés, pour qu’il puisse communiquer avec les trois containers serveurs web :

$ docker network connect --ip 192.168.0.2 réseau1 reverse-proxy

$ docker network connect --ip 192.168.1.2 réseau2 reverse-proxy

$ docker network connect --ip 192.168.2.2 réseau3 reverse-proxy

4.3.2 – Côté serveurs web :

Il n’y a pas de configuration à faire du côté des serveurs web.

4.3.3 – Côté client :

Comme les trois noms de domaine « site1.com », « site2.com », et « site3.com » ne sont pas enregistrés dans un DNS, il faut les définir localement sur la machine locale. Pour cela, on n’a qu’à modifier le fichier « /etc/hosts » en ajoutant une ligne pour chaque nom de domaine.

172.17.0.2      site1.com

172.17.0.2      site2.com

172.17.0.2      site3.com

Il faut noter que l’adresse IP est la même pour les trois noms de domaine, et, est celle du reverse-proxy. En effet, toute requête demandant une url d’un des trois noms de domaine dois être routée vers le reverse-proxy. Et c’est ce dernier qui fait l’aiguillage.

5 – Tests & Vérifications

Pour vérifier que tout est bien mis en place, il suffit d’ouvrir une navigateur web et de saisir les url des trois sites web : « site1.com », « site2.com », et « site3.com ».

Les figures suivante montrent bien le résultat :

Il est possible également de faire la vérification en utilisant la commande « curl » :

$ curl site1.com

$ curl site2.com

$ curl site3.com

6 – Conclusion

Dans cette article, nous avons vu comment mettre en place un reverse-proxy et trois serveurs web en utilisant des containers docker. Le rôle du reverse-proxy et de recevoir toutes les requêtes web arrivant sur la machines, ensuite, il s’en charge de les aiguiller, selon le nom de domaine demandé, vers les différents serveurs web. Ces derniers peuvent se trouver dans différents réseaux.

Le reverse-proxy se charge également de relayer les réponses générer par les serveurs web aux clients qui ont émis les requêtes.